using System;
using System.Collections.Generic;
using CLELCore.Assembly;
using opt.Analysis.Graph.CallGraph;

namespace opt.Analysis.Graph.CallGraph.CallGraphVisitor
{
	public class CallGraphVisitor<T,U> where U : NodeInfo,new()
					where T : ArcInfo,new()
	{
		private CallGraph<T,U> _cg;

		public CallGraphVisitor(CallGraph<T,U> cg)
		{
			if(cg == null)
				throw new ArgumentException("Call Graph cannot be null");
			_cg = cg;
		}

		public void Accept(IGraphVisit<T,U> visit)
		{
			int roots_count = _cg.Count;
			int arc_count;
			int i,j;
			GraphNode<T,U> root,node;
			Token node_token;
			Dictionary<Token,Boolean> seen = new Dictionary<Token,Boolean>();
			Stack<GraphNode<T,U>> next = new Stack<GraphNode<T,U>>();
			for(i = 0;i < roots_count;i++)
			{
				root = _cg[i];
				next.Push(root);
				while(next.Count > 0)
				{
					node = next.Pop();
					node_token = node.Data.MethodToken;
					if(!seen.ContainsKey(node_token))
					{
						seen.Add(node_token,true);
						visit.Visit(node);

						arc_count = node.Count;
						for(j = 0;j < arc_count;j++)
						{
							next.Push(node[j].Next);
						}
					}
				}
			}
		}
	}
}
